package crawler.model;

import crawler.common.PostData;
import business.service.MongoDbFactory;
import business.service.TTimSaoService;
import com.google.common.base.Joiner;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import crawler.common.CategoryData;
import crawler.common.ConfigFactory;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.bson.types.ObjectId;

public class CategoryModel {

    private static final String POST_COLLECTION = "category";
    private static final Logger logger = Logger.getLogger(CategoryModel.class);
    private static final Lock createLock_ = new ReentrantLock();
    private static CategoryModel _instance = null;

    public static CategoryModel getInstance() {
        if (_instance == null) {
            createLock_.lock();
            try {
                if (_instance == null) {
                    _instance = new CategoryModel();

                }
            } finally {
                createLock_.unlock();
            }
        }
        return _instance;
    }

    public CategoryModel() {
        try {
        } catch (Exception ex) {
            logger.error("PostModel: " + ex);
        }
    }

    public List<CategoryData> getList(int start, int limit) {
        List<CategoryData> lstPost = new LinkedList<>();
        try {
            BasicDBObject basicDBObject = new BasicDBObject("createdAt", -1);
            DB db = MongoDbFactory.getConnection();
            DBCollection coll = db.getCollection(POST_COLLECTION);
            DBCursor cursor = coll.find().sort(basicDBObject);

            if (limit != -1) {
                cursor = cursor.skip(start).limit(limit);
            }

            while (cursor.hasNext()) {
                DBObject dbObject = cursor.next();
                lstPost.add(fromDB(dbObject));
            }
        } catch (Exception ex) {
            logger.error("PostModel.getPost: " + ex.getMessage(), ex);
        }
        return lstPost;
    }
    public List<CategoryData> getList() {
        List<CategoryData> lst = new LinkedList<>();
        lst.add(new CategoryData("54cb3816e4b046bc6c9e45a2", "sao_vbiz", "Sao VBiz", 0L));
        lst.add(new CategoryData("546ea896e4b0c5c2626d3f70", "sao_quoc-te", "Sao Quốc tế", 0L));
        lst.add(new CategoryData("546ea891e4b0c5c2626d3f6e", "nhac_vpop", "Nhạc VPop", 0L));
        lst.add(new CategoryData("546ea885e4b0c5c2626d3f6c", "nhac_quoc-te", "Nhạc Quốc tế", 0L));
        lst.add(new CategoryData("546ea87fe4b0c5c2626d3f6a", "phim", "Phim", 0L));
        lst.add(new CategoryData("54cb3816e4b046bc6c9e45a2", "phim_rap", "Phim Rạp", 0L));
        lst.add(new CategoryData("546ea896e4b0c5c2626d3f70", "phim_truyen-hinh", "Phim Truyền Hình", 0L));
        lst.add(new CategoryData("546ea891e4b0c5c2626d3f6e", "dep", "Đẹp", 0L));
        lst.add(new CategoryData("546ea885e4b0c5c2626d3f6c", "dep_thoi-trang-sao", "Đẹp: thời trang sao", 0L));
        lst.add(new CategoryData("546ea87fe4b0c5c2626d3f6a", "dep_xu-huong", "Đẹp: Xu hướng", 0L));
        lst.add(new CategoryData("54cb3816e4b046bc6c9e45a2", "la_kham-pha", "Lạ: Khám Phá", 0L));
        lst.add(new CategoryData("546ea896e4b0c5c2626d3f70", "la_gioi-tre", "Lạ: Giới trẻ", 0L));
        lst.add(new CategoryData("546ea891e4b0c5c2626d3f6e", "sport", "Thể thao", 0L));
        lst.add(new CategoryData("546ea885e4b0c5c2626d3f6c", "bi-quyet_meo-vat", "Bí quyết: Mẹo vặt", 0L));
        lst.add(new CategoryData("546ea87fe4b0c5c2626d3f6a", "bi-quyet_khoe-dep", "Bí quyết: Khỏe đẹp", 0L));
        
        return lst;
    }
    public List<CategoryData>getListThrift(){
        List<CategoryData> lstResult = new LinkedList<>();
        try {
            String host = ConfigFactory.getParam("thrift", "host");
            int port = Integer.valueOf(ConfigFactory.getParam("thrift", "port_cate"));
            final TSocket socket = new TSocket(host, port);
            socket.setTimeout(10000);
            final TTransport transport = new TFramedTransport(socket);
            final TProtocol protocol = new TBinaryProtocol(transport);
            final TTimSaoService.Client client = new TTimSaoService.Client(protocol);
            transport.open();
            List<Map<String, String>> allCategory = client.getAllCategory();
            for (Map<String, String> category : allCategory) {
                String id = category.get("id");
                String name = category.get("name");
                CategoryData categoryData = new CategoryData("0", id,name, 0);
                lstResult.add(categoryData);
            }
            transport.close();

        } catch (TException e) {
            logger.error("SessionModel.getUserLogin:" + e.getMessage(), e);
        }

        return lstResult;
    }
    public CategoryData getById(String id) {
        try {
            BasicDBObject basicDBObject = new BasicDBObject("_id", new ObjectId(id));
            DB db = MongoDbFactory.getConnection();
            DBCollection coll = db.getCollection(POST_COLLECTION);
            DBCursor cursor = coll.find(basicDBObject);
            if (cursor.hasNext()) {
                DBObject dbObject = cursor.next();
                CategoryData postData = fromDB(dbObject);
                return postData;
            }
        } catch (Exception ex) {
            logger.error("PostModel.getPostById: " + ex.getMessage(), ex);
        }
        return null;
    }

    public static CategoryData fromDB(DBObject dbObject) {
        String objectId = ((ObjectId) dbObject.get("_id")).toString();
        String code = (String) dbObject.get("code");
        String name = (String) dbObject.get("name");
        long createdAt = (long) dbObject.get("createdAt");
        CategoryData postData = new CategoryData(objectId, code, name, createdAt);
        return postData;
    }

    public long getPostCount(String pid) {
        long count = 0;
        try {
            DB db = MongoDbFactory.getConnection();
            DBCollection coll = db.getCollection(POST_COLLECTION);
            count = coll.getCount();
        } catch (Exception ex) {
            logger.error("PostModel.getPostCount: " + ex.getMessage(), ex);
        }
        return count;
    }

    public boolean deletePost(String id) {
        try {
            DB db = MongoDbFactory.getConnection();
            DBCollection coll = db.getCollection(POST_COLLECTION);
            coll.remove(new BasicDBObject("_id", new ObjectId(id)));

            return true;
        } catch (Exception ex) {
            logger.error("PostModel.deletePost: " + ex.getMessage(), ex);
        }
        return false;
    }

    public String addNewPost(PostData postData) {
        String id = "";
        DB db = null;
        DBCollection coll;
        try {
            BasicDBObject basicDBObject = generateObject(postData);

            db = MongoDbFactory.getConnection();
            coll = db.getCollection(POST_COLLECTION);
            coll.insert(basicDBObject);

            ObjectId objectId = (ObjectId) basicDBObject.get("_id");
            id = objectId.toString();
        } catch (Exception ex) {
            logger.error("PostModel.addPost: " + ex.getMessage(), ex);
        }
        return id;
    }

    public boolean updatePost(PostData postData) {
        try {
            BasicDBObject basicDBObject = generateObject(postData);

            DB db = MongoDbFactory.getConnection();
            DBCollection coll = db.getCollection(POST_COLLECTION);

            BasicDBObject updateDBObject = new BasicDBObject("$set", basicDBObject);
            BasicDBObject searchDBQuery = new BasicDBObject("_id", new ObjectId(postData.getId()));
            coll.update(searchDBQuery, updateDBObject);
            return true;
        } catch (Exception ex) {
            logger.error("PostModel.updatePost: " + ex.getMessage());
        }
        return false;
    }

    public boolean checkPostExists(String link) {
        try {
            DB db = MongoDbFactory.getConnection();
            DBCollection coll = db.getCollection(POST_COLLECTION);
            BasicDBObject queryDBObject = new BasicDBObject("url", link);
            DBCursor cursor = coll.find(queryDBObject);

            if (cursor.hasNext()) {
                return true;
            }
        } catch (Exception ex) {
            logger.error("PostModel.checkPostExists: " + ex.getMessage(), ex);
        }
        return false;
    }

    private BasicDBObject generateObject(PostData postData) {
        BasicDBObject basicDBObject = new BasicDBObject()
                .append("site", postData.getSite())
                .append("category", postData.getCategory())
                .append("title", postData.getTitle())
                .append("thumb", postData.getThumb())
                .append("url", postData.getUrl())
                .append("desc", postData.getDesc())
                .append("content", postData.getContent())
                .append("images", Joiner.on(",").join(postData.getImages()))
                .append("tags", postData.getTags())
                .append("published", postData.getPublished())
                .append("author", postData.getJournalist())
                .append("created", postData.getCreated())
                .append("thumbFb", postData.getThumbFb())
                .append("urlFb", postData.getUrlFb())
                .append("titleFb", postData.getTitleFb())
                .append("descFb", postData.getDescFb())
                .append("siteFb", postData.getSiteFb());
        return basicDBObject;
    }
}
